package com.oa.organization.service;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.oa.organization.dao.OrganizationDao;
import com.oa.organization.dto.OrganizationDto;
import com.oa.organization.dto.OrganizationPieDto;
import com.oa.organization.entity.Organization;
import com.oa.organization.entity.OrganizationTree;
import com.oa.system.dao.UserInfoDao;
import com.oa.system.entity.UserInfo;

@Service
@Transactional
public class OrganizationServiceImpl implements OrganizationService {
	@Resource
	private OrganizationDao organizationDao;
	@Resource
	private UserInfoDao userInfoDao;

	@Override
	@Transactional(readOnly = true)
	public Iterable<OrganizationDto> findAllOrganization() {
		Iterable<Organization> organizatios = organizationDao.findAll();
		List<OrganizationDto> dtoList = new ArrayList<>();
		OrganizationDto organizationDto;

		for (Organization organization : organizatios) {
			organizationDto = new OrganizationDto();
			organizationDto.setId(organization.getId());
			organizationDto.setName(organization.getName());
			organizationDto.setLeadId(organization.getLeadId());
			organizationDto.setLead(organization.getLeadName());

			if (organization.getParent() != null) {
				organizationDto.setParent(organization.getParent().getName());
				organizationDto.setParentId(organization.getParent().getId());
			}

			dtoList.add(organizationDto);
		}

		return dtoList;
	}

	@Override
	@Transactional(readOnly = true)
	public List<OrganizationTree> findNodes(Long parentId) {
		List<OrganizationTree> nodeList = new ArrayList<>();
		List<Organization> lists;

		if (parentId == null) {
			lists = organizationDao.findParentNode();
		} else {
			lists = organizationDao.findChildrenNodeById(parentId);
		}

		OrganizationTree node;

		for (Organization organization : lists) {
			node = new OrganizationTree();
			node.setId(organization.getId());
			node.setName(organization.getName());
			node.setLeadId(organization.getLeadId());
			node.setLead(organization.getLeadName());
			node.setCount(count(organization.getId()));
			node.setGlyph("xf0f8@FontAwesome");

			if (organization.getChildren() != null && organization.getChildren().size() > 0) {
				node.setLeaf(false);
			} else {
				node.setLeaf(true);
			}

			if (organization.getParent() != null) {
				node.setParent(organization.getParent().getName());
				node.setParentId(organization.getParent().getId());
				node.setGlyph("xf27e@FontAwesome");
			}

			nodeList.add(node);
		}

		return nodeList;
	}

	@Override
	public Iterable<OrganizationPieDto> getOrganizationPie() {
		Iterable<Organization> organizatios = organizationDao.findAll();
		List<Organization> parentList = organizationDao.findParentNode();

		int parentCount = 0;
		for (Organization organization : parentList) {
			parentCount += count(organization.getId());
		}

		List<OrganizationPieDto> organizationPieDtoList = new ArrayList<>();
		for (Organization organization : organizatios) {
			if (organization.getChildren().isEmpty()) {
				OrganizationPieDto organizationPieDto = new OrganizationPieDto();
				int count = count(organization.getId());

				organizationPieDto.setName(organization.getName());
				organizationPieDto.setCount(count);
				organizationPieDto.setAngle((float) count / (float) parentCount);
				organizationPieDtoList.add(organizationPieDto);
			}
		}

		return organizationPieDtoList;
	}

	@Override
	public void saveOrUpdateOrganization(OrganizationDto organizationDto) {
		Organization organization = new Organization();

		organization.setName(organizationDto.getName());
		organization.setLeadId(organizationDto.getLeadId());
		organization.setLeadName(organizationDto.getLead());

		if (organizationDto.getId() != null) {
			organization.setId(organizationDto.getId());
		}

		Long id = organizationDto.getParentId();
		if (id != null) {
			Organization parent = organizationDao.findOne(id);
			organization.setParent(parent);
		}

		organizationDao.save(organization);
	}

	@Override
	public void deleteOrganization(Long id) {
		Organization organization = organizationDao.findOne(id);
		Organization parent = organization.getParent();
		List<Organization> children = organization.getChildren();

		List<UserInfo> userInfoList = userInfoDao.findByDeptId(id);

		for (UserInfo userInfo : userInfoList) {
			userInfo.setDept(null);
		}

		userInfoDao.save(userInfoList);

		if (parent != null) {
			parent.getChildren().remove(organization);
			parent.getChildren().addAll(children);
			for (Organization o : children) {
				o.setParent(parent);
			}
			organization.setChildren(null);
			organization.setParent(null);
			organizationDao.save(parent);
		} else {
			for (Organization o : children) {
				o.setParent(null);
			}
			organization.setChildren(null);
		}

		organizationDao.save(children);
		organizationDao.save(organization);
		organizationDao.delete(organization);
	}

	// 递归计算部门的总人数（当前部门及其子部门）
	private int count(Long id) {
		Organization organization = organizationDao.findOne(id);
		List<Organization> children = organization.getChildren();
		int count = userInfoDao.countByDeptId(id);

		if (!children.isEmpty()) {
			for (Organization o : children) {
				count += count(o.getId());
			}
		}

		return count;
	}

}
